perm filename KILLER.SAI[PNT,HE] blob sn#326348 filedate 1978-01-03 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00004 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	ENTRY
C00005 00003	! declarations and procedures
C00010 00004	! killcd
C00016 ENDMK
C⊗;
ENTRY;

BEGIN "KILLER"

REQUIRE "MACROS.SAI[PNT,HE]" SOURCE_FILE;
REQUIRE "RECORD.DEF[PNT,HE]" SOURCE_FILE;

DEFINE  KIL= 0,
	DECL=1,
      	DEL=2,
	ASG=3,
	AFX=4,
	CPY=5;

	! information about the state is saved depending on the instruction:
	  kil=not killable instruction,
	  decl=declaration instruction,
	  del=deletion instruction,
	  asg=assignment instruction,
	  afx=affix or unfix instruction,
	  cpy=merge instruction;

		! in MAINPR.SAI[PNT,HE];
EXTERNAL INTEGER $ROW;	! row in $YMTAB of last checked symbol;
EXTERNAL STRING $TRLST,$FRLST,$SCLST,$VTLST,$RTLST,$OULST;	! used for the display;
EXTERNAL RPTR(SYMBOL) PROCEDURE CHECK(STRING SYMB;INTEGER NM);
EXTERNAL RPTR(SCALAR,VECTOR,ROT,TRANS,FRAME) PROCEDURE MK_REC(INTEGER TYPE);

		! in OPERAT.SAI[PNT,HE];
EXTERNAL PROCEDURE LINKFR(RPTR(FRAME) N,D);	
EXTERNAL PROCEDURE UNLINK(RPTR(FRAME) N);
! declarations and procedures;

RCLASS SAVED (INTEGER ADDR,TYPE;RPTR(SYMBOL)SYMBOL;RANY OBJECT;
	RPTR(FRAME)DAD;INTEGER LINK;RPTR(SAVED)NEXT);

RPTR(SAVED) KILL;

DEFINE #NW = -1;			
DEFINE #NWFR= -2;

INTERNAL PROCEDURE SAVNEW(RPTR(SYMBOL)EL;INTEGER TYPE);
	BEGIN
	RPTR(SAVED)TEMP;
	TEMP←NEW_RECORD(SAVED);
	SAVED:ADDR[TEMP]←$ENTRY[TYPE]-1;	! entry in $YMTAB(last created symb);
	SAVED:TYPE[TEMP]←IF TYPE=#FR THEN #NWFR ELSE #NW;
	SAVED:OBJECT[TEMP]←SYMBOL:OBJECT[EL];	! se e` nuovo conservo il ptr, se no;
	SAVED:NEXT[TEMP]←KILL;			! conservo il ptr al record temporaneo;
	KILL←TEMP;
	END;

INTERNAL PROCEDURE INIKIL;
	BEGIN
	KILL←NULL_RECORD;
	END;

	! returns a rptr to a new record of class type. The record is not inserted
	  in $YMTAB (temporary record). The values of the record EL are copied into;

RANY PROCEDURE SAVREC(INTEGER TYPE;RPTR(SYMBOL)EL);
	BEGIN
	RANY TEMP,OBJ;
	OBJ←SYMBOL:OBJECT[EL];
	IF TYPE=#SC
	   THEN BEGIN
		TEMP←MK_REC(#SC);SCALAR:VALUE[TEMP]←SCALAR:VALUE[OBJ];
		END
	ELSE IF TYPE=#VT
	   THEN BEGIN
		TEMP←MK_REC(#VT);VECTOR:XC[TEMP]←VECTOR:XC[OBJ];
		VECTOR:YC[TEMP]←VECTOR:YC[OBJ];VECTOR:ZC[TEMP]←VECTOR:ZC[OBJ];
		END
	ELSE IF TYPE=#RT 
	   THEN BEGIN
		TEMP←MK_REC(#TR);
		ARRTRAN(TRANS:XF[TEMP],ROT:XF[OBJ]);
		END
	ELSE IF TYPE=#TR 
	   THEN BEGIN
		TEMP←MK_REC(#TR);
		ARRTRAN(TRANS:XF[TEMP],TRANS:XF[OBJ]);
		END
	ELSE  IF TYPE=#FR
	   THEN	BEGIN
		TEMP←MK_REC(#TR);
		ARRTRAN(TRANS:XF[TEMP],FRAME:XF[OBJ]);
		END;
	RETURN(TEMP);
	END;

INTERNAL PROCEDURE SAVOLD(RPTR(SYMBOL)EL;INTEGER TYPE);
	BEGIN
	RPTR(SAVED)TEMP;RANY OLDPTR;
	TEMP←NEW_RECORD(SAVED);
	SAVED:ADDR[TEMP]←$ROW;
	SAVED:TYPE[TEMP]←TYPE;
	SAVED:SYMBOL[TEMP]←EL;
	OLDPTR←SAVREC(TYPE,EL);			! creates a new record and copies valus;
	SAVED:OBJECT[TEMP]←OLDPTR;
	SAVED:NEXT[TEMP]←KILL;
	KILL←TEMP;
	CASE TYPE OF
	     BEGIN "CASE"
	[#SC]	$SCLST←NULL;
	[#VT]	$VTLST←NULL;
	[#RT]	$RTLST←NULL;
	[#FR]   $FRLST←NULL;
	[#TR]   $TRLST←NULL
	     END "CASE";
	END;

INTERNAL PROCEDURE SAVTRE(RPTR(SYMBOL)EL);
	BEGIN
	RPTR(FRAME)FRN;
	FRN←SYMBOL:OBJECT[EL];
	SAVOLD(EL,#FR);			! saves the values of the frame;
	SAVED:DAD[KILL]←FRAME:DAD[FRN];		! the pointer to its dad;
	SAVED:LINK[KILL]←FRAME:HOWLINKED[FRN]; 	! the kind of affixment;
	END;

INTERNAL PROCEDURE SAVFR(RPTR(FRAME) N);
	BEGIN
	RPTR(SYMBOL)EL;
	! if there are some #RGDLK, finds the pointer to the first frame
	  not rigidly affixed, and saves its values;
	EL←CHECK(FRAME:PNAME[N],#FR);
	SAVOLD(EL,#FR);
	END;
! killcd;

PROCEDURE TREE_RECOVER(RPTR(SAVED) TEMP);
	BEGIN
	LINKFR(symbol:object[SAVED:symbol[TEMP]],SAVED:DAD[TEMP]);	! links the frames;
	FRAME:HOWLINKED[symbol:object[SAVED:symbol[TEMP]]]←SAVED:LINK[TEMP];
	END;

	! kills $LAST instruction: only declarations, deletions, assignments
	  and tree operations can be killed. The value of $LAST indicates the
	  type of $LAST executed instruction;

INTERNAL PROCEDURE KILLCD(INTEGER LAST);
	BEGIN
	RPTR(SAVED)TEMP;
	CASE LAST OF
	BEGIN "CASE"
	[KIL]   PRINT("sorry...I can't ",CRLF);		! unkillable instruction;
	[DECL]  BEGIN
		TEMP←KILL;
		WHILE TEMP DO		! declaration;
		      BEGIN
		! deletes the new created symbols, the frames are unlinked;
		      $YMTAB[SAVED:ADDR[TEMP]]←NULL_RECORD;
		      IF SAVED:TYPE[TEMP]=#NWFR 
			 THEN UNLINK(SAVED:OBJECT[TEMP]);
		      TEMP←SAVED:NEXT[TEMP];
		      END;
		$SCLST←$VTLST←$RTLST←$TRLST←$FRLST←NULL;
		END;
	[DEL]   BEGIN 
		BOOLEAN TREE;		! deletion;
		TEMP←KILL;
		WHILE TEMP DO
		      BEGIN
		! inserts symbols deleted and restores values and tree structure;
		      $YMTAB[SAVED:ADDR[TEMP]]←SAVED:SYMBOL[TEMP];
		      IF SAVED:TYPE[TEMP]=#FR THEN TREE_RECOVER(TEMP);
		      TEMP←SAVED:NEXT[TEMP];
		      END;
		$SCLST←$VTLST←$RTLST←$TRLST←$FRLST←NULL;
		END;
	[ASG]   BEGIN				! assignment;
		INTEGER TYPE;RPTR(SYMBOL)EL;RANY OBJ,OLD;RPTR(SAVED)TEMP;
		TEMP←KILL;
		WHILE TEMP DO
			BEGIN
		! if symbol is a new defined one it is simply deleted, otherwise
		  old values and tree structure are restored ;
			TYPE←SAVED:TYPE[TEMP];
			EL←SAVED:SYMBOL[TEMP];
			OLD←SAVED:OBJECT[TEMP];
			$YMTAB[SAVED:ADDR[TEMP]]←EL;
			IF TYPE≠#NW
			   THEN IF TYPE=#NWFR
				   THEN UNLINK(OLD)
				ELSE 
				IF TYPE=#SC OR TYPE=#VT
				   THEN SYMBOL:OBJECT[EL]←OLD
				ELSE IF TYPE=#RT
				   THEN ARRTRAN(ROT:XF[SYMBOL:OBJECT[EL]],
						TRANS:XF[OLD])
				ELSE IF TYPE=#TR
				   THEN ARRTRAN(TRANS:XF[SYMBOL:OBJECT[EL]],
						TRANS:XF[OLD])
				ELSE ARRTRAN(FRAME:XF[SYMBOL:OBJECT[EL]],
	         				TRANS:XF[OLD]);
			TEMP←SAVED:NEXT[TEMP];
			END;
		$SCLST←$VTLST←$RTLST←$TRLST←$FRLST←NULL;
		END;

	[AFX]   BEGIN 				! affix/unfix;
		! restores previous structure: if a new frame has been created
		  it is unlinked and deleted, otherwise previous values and 
		  structure are restored;
		IF TEMP←SAVED:NEXT[KILL]
		   THEN BEGIN			! a new frame was created;
			IF SAVED:TYPE[TEMP]=#NWFR
			   THEN BEGIN
				$YMTAB[SAVED:ADDR[TEMP]]←NULL_RECORD;
				UNLINK(SAVED:OBJECT[TEMP]);
				IF TEMP←SAVED:NEXT[TEMP]
				   THEN	BEGIN		! that was a trans;
					$YMTAB[SAVED:ADDR[TEMP]]←SAVED:SYMBOL[TEMP];
					ARRTRAN(TRANS:XF[SYMBOL:OBJECT[SAVED:SYMBOL[TEMP]]],
						TRANS:XF[SAVED:OBJECT[TEMP]]);
					$TRLST←NULL;
					END;
				END;
			END
		   ELSE BEGIN
			$YMTAB[SAVED:ADDR[KILL]]←SAVED:SYMBOL[KILL];
			ARRTRAN(FRAME:XF[SYMBOL:OBJECT[SAVED:SYMBOL[KILL]]],
				TRANS:XF[SAVED:OBJECT[KILL]]);
			TREE_RECOVER(KILL);
			END;
		$FRLST←NULL;
		END;
	[CPY]  BEGIN
		TEMP←KILL;
		WHILE TEMP DO		! merge;
			BEGIN  
			! unlinks and deletes new frames;
		 	UNLINK(SAVED:OBJECT[TEMP]);
	 		$YMTAB[SAVED:ADDR[TEMP]]←NULL_RECORD;
			TEMP←SAVED:NEXT[TEMP];
		      END;
		END
	END "CASE";
	END;

END "KILLER";